import React, {FC, useCallback, useEffect, useMemo, useRef} from "react";
import useStateRef from "../../customUse/useStateRef.tsx";
import {AxiosGet} from "../../services/HttpService.tsx";
import {Button, Input, Select, Space} from "antd";
import "./css/CodeRuleInput.less";
import {getLocale} from "../../../i18n/i18n.tsx";
import {useTranslation} from "react-i18next";
import Config from "../../Config.tsx";
import {showMessage} from "../../reducer/MsgReducer.tsx";


interface CodeRuleInputProps {
    menuId: string,
    key: string,
    value?: any,
    ds?: any,
    params?: any,
    disabled?: boolean,
    onChange: Function
}

const CodeRuleInput: FC<CodeRuleInputProps> = (props) => {
    const {t} = useTranslation();

    const valueRef = useRef([]);
    const listRef = useRef([]);
    const [list, setList] = useStateRef([], listRef),
        [valueList, setValueList] = useStateRef([], valueRef);

    const handleChange: Function = useCallback((values: any) => {
        for (let i: number = 0; i < values.length; i++) {
            if (!values[i]) {
                return false;
            }
        }
        props.onChange && props.onChange(values.join(""));
    }, [props.onChange]);

    const loadList: Function = useCallback(async () => {
        const {params = {}}: { params?: any } = props;
        let {data}: { data: any[] } = await AxiosGet("/codeRuleEntry/list", {
            id: params.codeRuleId,
            [Config.axiosSerMenuKey]: props.menuId
        });
        let values: any[] = [];
        data.forEach((item: any) => {
            values.push(item.defaultValue || "");
        })
        setList(data);
        setValueList(values);
    }, [props.menuId]);

    const init: Function = useCallback(async () => {
        if (!props.disabled) {
            loadList();
        }
    }, [props.disabled, props.menuId]);

    const handleAssign: Function = useCallback(async () => {
        let values: string[] = valueRef.current;
        for (let i: number = 0; i < values.length - 1; i++) {
            if (!values[i]) {
                showMessage({
                    type: "error",
                    msg: t("assignMsg")
                });
                return false;
            }
        }
        const {params = {}}: { params?: any } = props;
        let newParams: any = {
            id: [...values].splice(0, values.length - 1).join(""),
            ...params,
            codeRuleSeralEntryId: listRef.current[listRef.current.length - 1].id
        };
        let {data}: { data: any } = await AxiosGet("/codeRuleEntry/getSeralNumber", {
            ...newParams,
            [Config.axiosSerMenuKey]: props.menuId
        });
        values[values.length - 1] = data;
        setValueList([...values]);
        handleChange(values);
    }, [props.params, props.menuId]);

    useEffect(() => {
        init()
    }, []);

    const renderInput = useCallback((node: any, index: number) => {
        return (
            <div className="sf_core_code_rule_input_input">
                <Input placeholder={getLocale(node.tipsCn, node.tipsEn)}
                       defaultValue={valueRef.current[index]}
                       onChange={(e) => {
                           valueRef.current[index] = e.target.value;
                       }} maxLength={node.length}
                       onBlur={() => {
                           handleChange(valueRef.current)
                       }}
                />
            </div>
        )
    }, [valueList])

    const renderLov = useCallback((node: any, index: number) => {
        return (
            <div className="sf_core_code_rule_input_lov">
                <Select
                    placeholder={getLocale(node.tipsCn, node.tipsEn)}
                    options={node.lovs.map((lov: any) => ({
                        ...lov,
                        label: getLocale(lov.nameCn, lov.nameEn)
                    }))}
                    onSelect={(value: any) => {
                        valueRef.current[index] = value;
                    }}
                    onBlur={() => {
                        handleChange(valueRef.current)
                    }}
                />
            </div>
        )
    }, [valueList]);

    const renderText = useCallback((node: any, index: number) => {
        return (
            <div className="sf_core_code_rule_input_text">
                {valueRef.current[index]}
            </div>
        )
    }, [valueList]);

    const getDomByType = useCallback((node: any, index: number) => {
        switch (node.type) {
            case "CodeRuleBlankEntry":
                return renderInput(node, index);
            case "CodeRuleFixedEntry":
                return renderText(node, index);
            case "CodeRuleLovEntry":
                return renderLov(node, index);
            case "CodeRulePropertyEntry":
                break;
            case "CodeRuleSeralEntry":
                return renderSerial(node, index);
        }
        return node.defaultValue;
    }, [valueList, props.params]);

    const renderSerial = useCallback((node: any, index: number) => {
        return (
            <div className="sf_core_code_rule_input_serial">
                <Space.Compact>
                    <Input placeholder={getLocale(node.tipsCn, node.tipsEn)}
                           value={valueRef.current[index]}
                           disabled={true}
                           maxLength={node.length}
                           onChange={(e) => {
                               valueRef.current[index] = e.target.value;
                           }}/>
                    <Button type="primary" onClick={handleAssign}>{t("assign")}</Button>
                </Space.Compact>
            </div>
        )
    }, [valueList, props.params, props.menuId]);

    const renderCodeRuleInput = useMemo(() => {
        const {ds = {}, disabled = false}: { ds?: any, disabled?: boolean } = props;
        if (disabled) {
            return ds.value || props.value || "";
        }
        if (!list || !valueList.length) {
            return null;
        }
        return (
            <div className="sf_core_code_rule_input">
                {list.map((item: any, index: number) => {
                    return getDomByType(item, index)
                })}
            </div>
        )
    }, [list, valueList, props.disabled, props.ds, props.params, props.menuId]);

    return (renderCodeRuleInput);
};

export default React.memo(CodeRuleInput);